#import <Foundation/Foundation.h>
#import <objc/runtime.h>

#import "framework/FWCommon.h"

#import "PICommon.h"
#import "PITask.h"

static UIColor* const kPIDefaultGreyTask = [[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:1.0] retain];
static UIColor* const kPIReplaceGreyTask = [[UIColor colorWithRed:0.0/255.0 green:0.0/255.0 blue:112.0/255.0 alpha:1.0] retain];


@implementation PITask

@synthesize dueDate, dueDateRaw, allDay, contextClassification, flagged, parent, child, parentKey, importance, priority, action, project, context, percentComplete, completionDate;

// ******************************************************************************************
#pragma mark -
#pragma mark Global sort functions

NSInteger compareNativeTasks(id value1, id value2, void* orders)
{
    PITask* task1 = (PITask*)value1;
    PITask* task2 = (PITask*)value2;
    
    for (NSArray* details in (NSArray*)orders) {
        SortFieldOptions sortField = (SortFieldOptions)[[details objectAtIndex:0] intValue];
        BOOL sortAsc = [[details objectAtIndex:1] boolValue];
        SortFieldNoneOrder noneOrder = (SortFieldNoneOrder)[[details objectAtIndex:2] intValue];
        
        NSInteger result = NSOrderedSame;

        switch (sortField) {
            case SortFieldOptionsImportance:
                if ((task1.importance == PIImportanceNone) && (task2.importance != PIImportanceNone))
                    result = noneOrder == SortFieldNoneOrderFirst ? NSOrderedAscending : NSOrderedDescending;
                else if ((task1.importance != PIImportanceNone) && (task2.importance == PIImportanceNone))
                    result = noneOrder == SortFieldNoneOrderFirst ? NSOrderedDescending : NSOrderedAscending;
                else if (task1.importance < task2.importance)
                    result = NSOrderedAscending;
                else if (task1.importance > task2.importance)
                    result = NSOrderedDescending;
                break;

            case SortFieldOptionsDueDate:
                if ([task1.dueDate isNull] && ![task2.dueDate isNull])
                    result = noneOrder == SortFieldNoneOrderFirst ? NSOrderedAscending : NSOrderedDescending;
                else if (![task1.dueDate isNull] && [task2.dueDate isNull])
                    result = noneOrder == SortFieldNoneOrderFirst ? NSOrderedDescending : NSOrderedAscending;
                else if ([task1.dueDate isNull] && [task2.dueDate isNull])
                    result = NSOrderedSame;
                else
                    result = [task1.dueDate compare:task2.dueDate];
                break;

            case SortFieldOptionsTitle:
                result = [task1.title compare:task2.title options:NSCaseInsensitiveSearch];
                break;

            case SortFieldOptionsNative:
                if (!task1.isNative && task2.isNative)
                    result = NSOrderedAscending;
                else if (task1.isNative && !task2.isNative)
                    result = NSOrderedDescending;
                break;

            default:
                break;
        }
        
        if (result != NSOrderedSame) {
            // Reverse sort order?
            if (!sortAsc) {
                if (result == NSOrderedAscending)
                    result = NSOrderedDescending;
                else
                    result = NSOrderedAscending;
            }
            
            return result;
        }
    }

    return NSOrderedSame;
}

NSInteger compareNativeTaskTitles(id value1, id value2, void* context)
{
    return [((PITask*)value1).title compare:((PITask*)value2).title options:NSCaseInsensitiveSearch];
}

// ******************************************************************************************
#pragma mark -
#pragma mark Initialisation and object management

+ (PITask*)nativeTaskWithKey:(NSString *)newKey version:(NSInteger)version title:(NSString *)newTitle icon:(NSString *)newIcon startDate:(NSDate *)newStart startDateRaw:(NSTimeInterval)newStartDateRaw dueDate:(NSDate *)newEnd dueDateRaw:(NSTimeInterval)newEndRaw allDay:(BOOL)newAllDay calendar:(NSString *)newCalendar calendarIcon:(NSString *)newCalIcon calendarColor:(UIColor *)newCalColor parentKey:(NSString *)newParent
{
    PITask* task = [[[PITask alloc] init] autorelease];
    
    task->key = [newKey copy];
    task->objectVersion = version;
    task->native = YES;
    
    task->title = [newTitle copy];
    task->icon = [newIcon copy];
    
    [task setStartDate:newStart];
    task->startDateRaw = newStartDateRaw;
    [task setDueDate:newEnd];
    task->dueDateRaw = newEndRaw;
    task->allDay = newAllDay;
    [task setCompletionDate:nil];
    
    task->calendar = [newCalendar copy];
    task->calendarIcon = [newCalIcon copy];
    task->calendarColor = [newCalColor retain];

    task->parentKey = [newParent copy];
    
    return task;
}

+ (PITask*)piTaskWithKey:(NSString *)newKey version:(NSInteger)version title:(NSString *)newTitle icon:(NSString *)newIcon startDate:(NSDate *)newStart startDateRaw:(NSTimeInterval)newStartDateRaw dueDate:(NSDate *)newEnd dueDateRaw:(NSTimeInterval)newEndRaw allDay:(BOOL)newAllDay calendar:(NSString *)newCalendar calendarIcon:(NSString *)newCalIcon calendarColor:(UIColor *)newCalColor parentKey:(NSString *)newParent
{
    PITask* task = [[[PITask alloc] init] autorelease];
    
    task->key = [newKey copy];
    task->objectVersion = version;
    task->native = NO;
    
    task->title = [newTitle copy];
    task->icon = [newIcon copy];
    
    [task setStartDate:newStart];
    task->startDateRaw = newStartDateRaw;
    [task setDueDate:newEnd];
    task->dueDateRaw = newEndRaw;
    task->allDay = newAllDay;
    [task setCompletionDate:nil];
    
    task->calendar = [newCalendar copy];
    task->calendarIcon = [newCalIcon copy];
    
    if ([newCalColor isEqual:kPIDefaultGreyTask])
        task->calendarColor = [kPIReplaceGreyTask retain];
    else
        task->calendarColor = [newCalColor retain];
    
    task->parentKey = [newParent copy];
    
    return task;
}

- (id)init
{
    self = [super init];
    if (self) {
        
        // Initialization code here.
    }
    
    return self;
}

- (void)dealloc
{
    [dueDate release];
    [completionDate release];
    
    [priority release];

    [project release];
    
    [parentKey release];
    
    [context release];

    [super dealloc];
}


// ******************************************************************************************
#pragma mark -
#pragma mark Object duplication

- (id)copyWithZone:(NSZone *)zone
{
    PITask* copy = [[[self class] allocWithZone:zone] init];
    
    copy->key = [self.key retain];
    copy->native = self.native;
    
    copy->title = [self.title retain];
    copy->icon = [self.icon retain];
    [copy setUpdateRequired:self.isUpdateRequired];
    copy->objectVersion = self.objectVersion;
    
    copy->contextClassification = self.contextClassification;
    copy->repeating = self.repeating;
    
    [copy setStartDate:self.startDate];
    copy->startDateRaw = self.startDateRaw;
    [copy setDueDate:self.dueDate];
    copy->dueDateRaw = self.dueDateRaw;
    copy->allDay = self.allDay;
    [copy setCompletionDate:self.completionDate];
    
    copy->calendar = [self.calendar retain];
    copy->calendarIcon = [self.calendarIcon retain];
    copy->calendarColor = [self.calendarColor retain];

    copy->flagged = self.flagged;
    copy->child = self.child;
    copy->parent = self.parent;
    copy->importance = self.importance;
    copy->action = self.action;
    copy->sensitivity = self.sensitivity;

    [copy setPriority:self.priority];
    [copy setProject:self.project];
    
    [copy setAlarms:self.alarms];

    copy->parentKey = [self.parentKey retain];
    
    return copy;
}


// ******************************************************************************************
#pragma mark -
#pragma mark Debugging functions

- (NSString*)shortDescription
{
    return [self description];
}

- (NSString*)description
{
    return [NSString stringWithFormat:
            @"<%@: %p;"
            " title = %@;"
            " key = %@;"
            " native = %i;"
            " version = %i;"
            " icon = %@;"
            " startDate = %@;"
            " startDateRaw = %.0f;"
            " dueDate = %@;"
            " dueDateRaw = %.0f;"
            " allDay = %i;"
            " calendar = %@;"
            " calendarIcon = %@;"
            " calendarColor = %@;"
            " importance = %i;"
            " priority = %@;"
            " action = %i;"
            " repeating = %i;"
            " project = %@;"
            " flagged = %i;"
            " parent = %i;"
            " child = %i;"
            " parentKey = %@;"
            " percentComplete = %i;"
            " context = %@;"
            " tags = %@;"
            " alarms = %@;"
            " notes = %@>",
            [self class],
            self,
            self.title,
            self.key,
            self.native,
            self.objectVersion,
            self.icon,
            self.startDate,
            self.startDateRaw,
            self.dueDate,
            self.dueDateRaw,
            self.allDay,
            self.calendar,
            self.calendarIcon,
            self.calendarColor,
            self.importance,
            self.priority,
            self.action,
            self.repeating,
            self.project,
            self.flagged,
            self.parent,
            self.child,
            self.parentKey,
            self.percentComplete,
            self.context,
            self.tags,
            self.alarms,
            self.notes];
}


// ******************************************************************************************
#pragma mark -
#pragma mark Information access

- (BOOL)hasDetails
{
    return !self.startDate.isNull ||
            !dueDate.isNull ||
            (priority && (priority.length > 0)) ||
            (project && (project.length > 0));
}

- (BOOL)isInProgress
{
    return (action == PIActionNone) || (action == PIActionNext) || (action == PIActionActive) || (action == PIActionPlanning);

}

@end
